package com.hhs.storage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.BeanUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hhs.storage.bean.*;
import com.hhs.storage.config.jwt.JwtProperty;
import com.hhs.storage.dao.BaseUserDao;
import com.hhs.storage.service.*;
import com.hhs.storage.config.jwt.JwtHelper;
import com.hhs.storage.util.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author shadow
 * @since 2018-09-29
 */
@Service
@Slf4j
@Transactional
public class BaseUserServiceImpl extends ServiceImpl<BaseUserDao, BaseUser> implements BaseUserService {

    @Resource
    BaseRoleUserService jxcRoleUserService;
    @Resource
    BaseRoleService baseRoleService;
    @Resource
    BasePermissionService basePermissionService;
    @Resource
    ContractService contractService;
    @Resource
    CarFleetService carFleetService;
    @Resource
    JwtProperty jwtProperty;
    @Resource
    PersonConfigService personConfigService;
    @Resource
    BaseDepartmentService baseDepartmentService;
    @Resource
    HttpServletRequest request;
    @Resource
    PersonalPlanService personalPlanService;
    @Resource
    ZrAttendanceSettingService zrAttendanceSettingService;
    @Resource
    BaseDepartmentUserService baseDepartmentUserService;

    @Override
    public Map<String, Object> addOrUpdate(BaseUser user, String roleFlag) {
        //如果新增的是车队长，必须设置车队类型
        if (SysUtil.ROLE_FLAG_CDZ.equals(roleFlag)) {
            if (user.getCarFleetType() == null) {
                return ResponseInfo.error("必须选择车队类型");
            }
        }
        List<BaseUser> tempList = this.baseMapper.selectList(new QueryWrapper<BaseUser>().eq("account_", user.getAccount()));
        //新增
        if (StringUtils.isEmpty(user.getId())) {
            if (StringUtils.isEmpty(user.getPassword())) {
                user.setPassword(Md5Util.getMD5("123456"));//初始化密码
            } else {
                user.setPassword(Md5Util.getMD5(user.getPassword()));
            }
            if (StringUtils.isEmpty(user.getNumber())) {
                user.setNumber(user.getAccount());//如果没有指定电话，那么账户同时是电话
            }
            user.setStatus(true);
            user.setCreateTime(LocalDateTime.now());
            //要确保账号的唯一性，判断账号是否已经存在
            if (tempList.size() > 0) {
                return ResponseInfo.error("账号已存在，请重新输入");
            }
            this.saveOrUpdate(user);
//            editRole(user.getId());
            if (roleFlag != null) {//新增用户时强制指定角色
                List<BaseRole> baseRoles = baseRoleService.list(new QueryWrapper<BaseRole>().eq("flag_", roleFlag));
                if (baseRoles.size() == 0) {
                    return ResponseInfo.error("错误的角色标示");
                }
                BaseRoleUser jru = new BaseRoleUser();
                jru.setUserId(user.getId());
                jru.setRoleId(baseRoles.get(0).getId());
                jxcRoleUserService.save(jru);
            }
        } else {//修改
            if (tempList.size() > 0 && !tempList.get(0).getId().equals(user.getId())) {
                return ResponseInfo.error("账号已存在，请重新输入");
            }
//            user.setPassword(Md5Util.getMD5(user.getPassword()));
            this.saveOrUpdate(user);
            //如果当前角色是车队长，编辑时修改所有名下车队类型
            if (SysUtil.ROLE_FLAG_CDZ.equals(roleFlag)) {
                UpdateWrapper<CarFleet> updateWrapper = new UpdateWrapper<CarFleet>();
                updateWrapper.eq("principal_id", user.getId());
                updateWrapper.set("type", user.getCarFleetType());
                carFleetService.update(updateWrapper);
            }
        }


        return ResponseInfo.success(null);
    }

    @Override
    public Map<String, Object> dele(String id) {
        //检查业务员是否关联合同
        QueryWrapper<Contract> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("principal", id);
        if (contractService.count(queryWrapper) > 0) {
            return ResponseInfo.error("用户有关联合同,不可删除");
        }
        //先删除关联角色数据
        jxcRoleUserService.remove(new QueryWrapper<BaseRoleUser>().eq("user_id_", id));
        this.remove(new QueryWrapper<BaseUser>().eq("id_", id));
        return ResponseInfo.success("删除成功");
    }

    @Override
    public Map<String, Object> editRole(String userId, String[] roleArr) {
        //当前操作人
        String curUserId = SysUtil.getLoginUserId(request);
        if (StringUtils.isEmpty(curUserId)) {
            return ResponseInfo.error("数据错误");
        }
        boolean isAdmin = baseRoleService.hasRole(SysUtil.ROLE_FLAG_ADMIN, curUserId);
        boolean isHr = baseRoleService.hasRole(SysUtil.ROLE_FLAG_HR, curUserId);
        //人事或者admin才可以
        if (isAdmin || isHr) {
            boolean adminOrBoss = isAdminOrBoss(userId);
            //人事不能操作老板和admin
            if (!isAdmin && adminOrBoss) {
                return ResponseInfo.error("无权限");
            }
            //删除旧的关联数据
            jxcRoleUserService.remove(new QueryWrapper<BaseRoleUser>().eq("user_id_", userId));
            //新增用户与角色关联
            for (String s : roleArr) {
                BaseRoleUser jru = new BaseRoleUser();
                jru.setUserId(userId);
                jru.setRoleId(s);
                jxcRoleUserService.save(jru);
            }
            return ResponseInfo.success();
        }
        return ResponseInfo.error("无权限");
    }

    @Override
    public Map<String, Object> oauth(String account, String password) {
        List<BaseUser> tempList = this.baseMapper.selectList(new QueryWrapper<BaseUser>()
                .eq("account_", account)
                .eq("password_", Md5Util.getMD5(password))
                .eq("status_", 1)
        );
        if (tempList.size() > 0) {
            BaseUser user = tempList.get(0);
            //角色信息
            List<BaseRole> roleList = baseRoleService.getByUserId(user.getId());
            String accessToken = "bearer " + JwtHelper.createJWT(account, user.getId(),
                    "userRole", jwtProperty.getBase64Secret());
            //权限信息
            List<BasePermission> perList = basePermissionService.getByUserId(user.getId());
            String perStr = ",,";
            for (BasePermission basePermission : perList) {
                perStr += basePermission.getFlag() + ',';
            }
            //系统布局配置
            PersonConfig personConfig =
                    personConfigService.getByType(PersonConfig.TYPE_SYS_LAYOUT, user.getId());
            Map<String, Object> resultMap = new HashMap<String, Object>();
            resultMap.put("code", 1);
            resultMap.put("userName", user.getName());
            resultMap.put("userId", user.getId());
            resultMap.put("token", accessToken);
            resultMap.put("photoUrl", user.getPhotoUrl());
            resultMap.put("roleList", roleList);
            if (personConfig != null) {
                resultMap.put("sysLayout", personConfig.getData());
            }
            resultMap.put("perStr", perStr);

            SysUtil.logsService.log(user.getId(), "登陆", "登陆认证", null);

            return resultMap;
        } else {
            return ResponseInfo.error("登录失败：账号或密码错误");
        }
    }

    /**
     * 获取用户角色与权限信息
     *
     * @param id
     * @return
     */
    @Override
    public Map<String, Object> getInfo(String id) {
        BaseUser user = this.getById(id);
        if (user == null) {
            return ResponseInfo.error("认证失败，请重新登录");
        }
        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("code", 1);
        resultMap.put("userName", user.getName());
        resultMap.put("photoUrl", user.getPhotoUrl());
        //角色信息
        List<BaseRole> roleList = baseRoleService.getByUserId(user.getId());
        List<String> roles = new ArrayList<>();
        for (int i = 0; i < roleList.size(); i++) {
            roles.add(roleList.get(i).getFlag());
        }
        resultMap.put("roles", roles);
        resultMap.put("roleList", roleList);
        return resultMap;
    }

    @Override
    public Map<String, Object> changePass(String userId, String password) {
        BaseUser user = new BaseUser();
        user.setId(userId);
        user.setPassword(Md5Util.getMD5(password));
        this.updateById(user);
        return ResponseInfo.success(null);
    }

    @Override
    public Map<String, Object> changePass(String createrId, String oldPass, String newPass) {
        BaseUser user = this.getById(createrId);
        if (!user.getPassword().equals(Md5Util.getMD5(oldPass))) {
            return ResponseInfo.error("原密码输入错误");
        }
        BaseUser temp = new BaseUser();
        temp.setId(createrId);
        temp.setPassword(Md5Util.getMD5(newPass));
        this.updateById(temp);
        return ResponseInfo.success(null);
    }

    @Override
    public Map<String, Object> changeStatus(BaseUser user) {
        this.updateById(user);
        return ResponseInfo.success(null);
    }

    @Override
    public Map<String, Object> getAll(InputParam inputParam) {
        QueryWrapper ew = new QueryWrapper<BaseUser>();
        if (StringUtils.isNotEmpty(inputParam.getName())) {
            ew.like("name_", inputParam.getName());
        }
        if (StringUtils.isNotEmpty(inputParam.getAccount())) {
            ew.like("account_", inputParam.getAccount());
        }
        ew.orderByAsc("order_num");
        Page<BaseUser> result = this.page(new Page<BaseUser>(
                inputParam.getPage(),
                inputParam.getSize()), ew);
        //获取每个用户的角色名称，方便前端展示
        for (BaseUser record : result.getRecords()) {
            List<BaseRole> roleList = baseRoleService.getByUserId(record.getId());
            if (roleList.size() > 0) {
                String temp = "";
                for (BaseRole o : roleList) {
                    temp += o.getName() + "，";
                }
                temp = temp.substring(0, temp.length() - 1);
                record.setRoleNames(temp);
            }
            //获取每个用户的部门名称，方便前端展示
            List<BaseDepartment> departList = baseDepartmentService.findByUserId(record.getId());
            if (departList.size() > 0) {
                String temp = "";
                for (BaseDepartment o : departList) {
                    temp += o.getName();
                    if (o.getType().equals(1)) {
                        temp += "-负责人";
                    } else if (o.getType().equals(2)) {
                        temp += "-职员";
                    }
                    temp += ",";
                }
                temp = temp.substring(0, temp.length() - 1);
                record.setDepartNames(temp);
            }
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("rows", result.getRecords());
        map.put("total", result.getTotal());
        map.put("code", 1);
        return map;
    }

    @Override
    public Map<String, Object> getUsersByRoleFlag(String flag) {
        List<BaseUser> users = this.baseMapper.getUsersByRoleFlag(flag);
        return ResponseInfo.success(users);
    }

    @Override
    public Map<String, Object> queryCarCaptain(InputParam inputParam) {
        if (StringUtils.isNotEmpty(inputParam.getName())) {
            inputParam.setName("%" + inputParam.getName() + "%");
        }
        if (StringUtils.isNotEmpty(inputParam.getCarFleetName())) {
            inputParam.setCarFleetName("%" + inputParam.getCarFleetName() + "%");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("rows", this.baseMapper.queryCarCaptain(inputParam));
        map.put("total", this.baseMapper.totalCarCaptain(inputParam));
        map.put("code", 1);
        return map;
    }

    @Override
    public Map<String, Object> getAllById(String userId) {
        if (StringUtils.isEmpty(userId)) {
            return ResponseInfo.error("参数错误");
        }
        BaseUser user = this.getById(userId);
        if (user == null) {
            return ResponseInfo.error("参数错误");
        }
        //角色信息
        List<BaseRole> roleList = baseRoleService.getByUserId(user.getId());
        //权限信息
        List<BasePermission> perList = basePermissionService.getByUserId(user.getId());
        //部门信息
        List<BaseDepartment> departList = baseDepartmentService.findByUserId(user.getId());
        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("code", 1);
        resultMap.put("user", user);
        resultMap.put("roleList", roleList);
        resultMap.put("perList", perList);
        resultMap.put("departList", departList);
        return resultMap;
    }

    @Override
    public Map<String, Object> addToDepart(BaseUser user, String roleFlag, String departId, Integer employeeType) {
        List<BaseUser> tempList = this.baseMapper.selectList(new QueryWrapper<BaseUser>().eq("account_", user.getAccount()));
        //新增
        if (StringUtils.isEmpty(user.getId())) {
            if (StringUtils.isEmpty(user.getPassword())) {
                user.setPassword(Md5Util.getMD5("123456"));//初始化密码
            } else {
                user.setPassword(Md5Util.getMD5(user.getPassword()));
            }
            if (StringUtils.isEmpty(user.getNumber())) {
                user.setNumber(user.getAccount());//如果没有指定电话，那么账户同时是电话
            }
            user.setStatus(true);
            user.setCreateTime(LocalDateTime.now());
            //要确保账号的唯一性，判断账号是否已经存在
            if (tempList.size() > 0) {
                return ResponseInfo.error("账号已存在，请重新输入");
            }
            this.saveOrUpdate(user);
            if (roleFlag != null) {//新增用户时强制指定角色
                List<BaseRole> baseRoles = baseRoleService.list(new QueryWrapper<BaseRole>().eq("flag_", roleFlag));
                if (baseRoles.size() == 0) {
                    return ResponseInfo.error("错误的角色标示");
                }
                BaseRoleUser jru = new BaseRoleUser();
                jru.setUserId(user.getId());
                jru.setRoleId(baseRoles.get(0).getId());
                jxcRoleUserService.save(jru);
            }
        } else {//修改
            if (tempList.size() > 0 && !tempList.get(0).getId().equals(user.getId())) {
                return ResponseInfo.error("账号已存在，请重新输入");
            }
            this.saveOrUpdate(user);
        }
        //关联部门
        baseDepartmentService.join(user.getId(), departId, null, employeeType);
        return ResponseInfo.success(null);
    }

    @Override
    public Map<String, Object> resetPass(String id) {
        String userId = SysUtil.getLoginUserId(request);
        if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(id)) {
            return ResponseInfo.error("数据错误");
        }
        boolean isAdmin = baseRoleService.hasRole(SysUtil.ROLE_FLAG_ADMIN, userId);
        boolean isHr = baseRoleService.hasRole(SysUtil.ROLE_FLAG_HR, userId);
        //人事或者admin才可以
        if (isAdmin || isHr) {
            boolean adminOrBoss = isAdminOrBoss(id);
            //人事不能重置老板和admin的密码
            if (!isAdmin && adminOrBoss) {
                return ResponseInfo.error("无权限");
            }
            BaseUser user = new BaseUser();
            user.setId(id);
            user.setPassword(Md5Util.getMD5("123456"));
            this.updateById(user);
            return ResponseInfo.success();
        }
        return ResponseInfo.error("无权限");
    }

    @Override
    public Map<String, Object> getByName(String name) {
//        if (StringUtils.isEmpty(name)) {
//            return ResponseInfo.success(null);
//        }
        QueryWrapper ew = new QueryWrapper<BaseUser>();
        if(!StringUtil.iszNull(name)){
            ew.like("name_", name);
        }
        ew.eq("status_", 1);
        ew.orderByAsc("order_num");
        List<BaseUser> list = this.list(ew);
        List<Map> res = new ArrayList<>();
        for (BaseUser user : list) {
            Map temp = new HashMap();
            temp.put("id", user.getId());
            temp.put("value", user.getName());
            res.add(temp);
        }
        return ResponseInfo.success(res);
    }

    @Override
    public int sum() {
        String[] excludeId = SysUtil.EXCLUDE_USERS;
        //排除管理员 以及 用户账号停用的数据
        List<BaseUser> tempList = this.baseMapper.selectList(
                new QueryWrapper<BaseUser>().eq("status_", 0));
        if (tempList != null && tempList.size() > 0) {
            String userId = SysUtil.getLoginUserId(request);
            String[] idArr = new String[tempList.size()];
            for (int i = 0; i < tempList.size(); i++) {
                idArr[i] = tempList.get(i).getId();
            }
            String[] both = (String[]) ArrayUtils.addAll(SysUtil.EXCLUDE_USERS, idArr);
            excludeId = both;
        }
        QueryWrapper<BaseUser> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.notIn("id_", excludeId);
        int count = this.count(userQueryWrapper);
        return count;
    }

    //处理出缺勤
    @Override
    public void doAbsenceAndAttendance(List<BaseUser> a, InputParam inputParam) {
        for (BaseUser user :
                a) {
            if (inputParam.getType() == 0) {      //日
                QueryWrapper<PersonalPlan> qw = new QueryWrapper<>();
                DateEasy da = new DateEasy();
                da.addDate(-1);
                qw.eq("work_date", da.toYYYYhMMhDD());
                qw.eq("user_id", user.getId());
                List<PersonalPlan> listp = personalPlanService.list(qw);
                double n = listp.size();//计划数目
                //得到设定的前一天的工作时数
                int nn = getWorkTotalCount(inputParam, user.getId());
                double atrace = 0.00;
                double abrace = 0.00;
                if (nn == -1) {
                    user.setAttendanceRace("-");
                    user.setAbsenceRace("-");
                } else {
                    if (nn == 0) {
                        atrace = 0.00;
                        abrace = 0.00;
                    } else {
                        atrace = n / (nn * 2.0);
                        abrace = 1 - atrace;
                    }
                    user.setAttendanceRace(NumberUtil.toDoubleCase(atrace*100 + "", 2) + "%");
                    user.setAbsenceRace(NumberUtil.toDoubleCase(abrace*100 + "", 2) + "%");
                }
            } else if (inputParam.getType() == 1) {//周
                DateEasy da = new DateEasy();
                int dayOfWeek = da.getDayOfWeek();
                DateEasy endday = new DateEasy();
                if (dayOfWeek == 1) {//如果是周一得上一周的
                    da.addDate(-7);
                    endday.addDate(-1);
                } else {
                    da = DateEasy.getTimesWeekMorning();
                    endday=new DateEasy(da).addDate(6);
                }
                QueryWrapper<PersonalPlan> qw = new QueryWrapper<>();
                qw.between("work_date", da.toLocalDate(), endday.toLocalDate());
                qw.eq("user_id", user.getId());
                List<PersonalPlan> listp = personalPlanService.list(qw);
                int n = listp.size();//计划数目
                //得到设定的这一周的工作时数
                int nn = getWorkTotalCount(inputParam, user.getId());
                double atrace = 0.00;
                double abrace = 0.00;
                double atraceday = 0.00;
                double abraceday = 0.00;
                if (nn == 0) {
                    atrace = 0.00;
                    abrace = 0.00;
                } else {
                    atrace = n / (nn * 2.0);
                    abrace = 1 - atrace;
                    atraceday = NumberUtil.toDoubleCase(atrace * 7 + "", 2);
                    abraceday = NumberUtil.toDoubleCase(7 - atrace * 7 + "", 2);
                }
                user.setAttendanceRace(NumberUtil.toDoubleCase(atrace*100 + "", 2) + "%");
                user.setAbsenceRace(NumberUtil.toDoubleCase(abrace*100 + "", 2) + "%");
                user.setAbsenceDays(abraceday + "");
                user.setAttendanceDays(atraceday + "");

            } else if (inputParam.getType() == 2) {//月
                DateEasy da = DateEasy.getTimesMonthMorning();
                DateEasy endday = new DateEasy();
                int dayOfMonth = new DateEasy().getDate();
                if (dayOfMonth == 1) {//如果是1号，就是上一个月
                    da.addMonth(-1);
                    dayOfMonth = da.getMaxDate();
                }
                //设置开始时间与结束时间
                inputParam.setStartDate(da.toLocalDate());
                inputParam.setEndDate(endday.toLocalDate());
                QueryWrapper<PersonalPlan> qw = new QueryWrapper<>();
                qw.between("work_date", da.toLocalDate(), endday.toLocalDate());
                qw.eq("user_id", user.getId());
                List<PersonalPlan> listp = personalPlanService.list(qw);
                int n = listp.size();//计划总数目
                //得到设定的这一月的工作时数
                int nn = getWorkTotalCount(inputParam, user.getId());
                double atrace = 0.00;
                double abrace = 0.00;
                double atraceday = 0.00;
                double abraceday = 0.00;
                if (nn == 0) {
                    atrace = 0.00;
                    abrace = 0.00;
                } else {
                    atrace = n / (nn * 2.0);
                    abrace = 1 - atrace;
                    atraceday = NumberUtil.toDoubleCase(atrace * dayOfMonth + "", 2);
                    abraceday = NumberUtil.toDoubleCase(dayOfMonth - atrace * dayOfMonth + "", 2);
                }
                user.setAttendanceRace(NumberUtil.toDoubleCase(atrace*100 + "", 2) + "%");
                user.setAbsenceRace(NumberUtil.toDoubleCase(abrace*100 + "", 2) + "%");
                user.setAbsenceDays(abraceday + "");
                user.setAttendanceDays(atraceday + "");
            }
        }
    }

    @Override
    public Map<String, Object> getUsersByRoleIds(String roleIds){
        String[] ids=roleIds.split(",");
        List<String> roleList=Arrays.asList(ids);
        List<BaseUser> fusers = this.baseMapper.getUsersByRoleIds(roleList);
        for (BaseUser bu :
                fusers) {
            List<BaseRole> bid = baseRoleService.getByUserId(bu.getId());
            String roleNames = bid.stream().map(item -> item.getName()).collect(Collectors.joining(","));
            bu.setRoleNames(roleNames);
        }
        return ResponseInfo.success(fusers);
    }

    /**
     * 得一工作总时数，
     *
     * @param inputParam type 0.天，1.周,2.月
     * @param userId
     * @return
     */
    private int getWorkTotalCount(InputParam inputParam, String userId) {
        if (inputParam.getType() == 0 || inputParam.getType() == 1) {
            QueryWrapper<ZrAttendanceSetting> qw = new QueryWrapper<>();
            qw.eq("target_id", userId);
            qw.eq("type", 1);//先找个人设定
            qw.lt("start_date", LocalDate.now());//设定时间小于今天
            qw.orderByDesc("start_date");
            List<ZrAttendanceSetting> list = zrAttendanceSettingService.list(qw);
            if (list.size() > 0) {//找到了
                int total = 0;
                if (inputParam.getType() == 0) {
                    total = getDayTotal(list);
                } else if (inputParam.getType() == 1) {
                    total = getWeekTotal(list, inputParam);
                }
                return total;
            } else {//没有找到，找领导
                String departHead = baseDepartmentUserService.isDepartHead(userId);
                if (!StringUtil.iszNull(departHead)) {//是领导
                    QueryWrapper<ZrAttendanceSetting> qw0 = new QueryWrapper<>();
                    qw0.isNull("target_id");//部门领导这两上为空
                    qw0.isNull("type");
                    qw0.lt("start_date", LocalDate.now());//设定时间小于今天
                    List<ZrAttendanceSetting> list0 = zrAttendanceSettingService.list(qw0);
                    if (list0.size() > 0) {//找到了就用领导的
                        int total = 0;
                        if (inputParam.getType() == 0) {
                            total = getDayTotal(list0);
                        } else if (inputParam.getType() == 1) {
                            total = getWeekTotal(list0, inputParam);
                        }
                        return total;
                    } else {//没有找到找部门和默认
                        return findDepartAndDefault(inputParam, userId);
                    }
                } else {//不是领导直接找部门和默认
                    return findDepartAndDefault(inputParam, userId);
                }
            }
        } else if (inputParam.getType() == 2) {
            QueryWrapper<ZrAttendanceSetting> qw = new QueryWrapper<>();
            qw.eq("target_id", userId);
            qw.eq("type", 1);//先找个人设定
            qw.lt("start_date", inputParam.getStartDate());//得到开始日期前的设置
            qw.orderByDesc("start_date");
            List<ZrAttendanceSetting> list = zrAttendanceSettingService.list(qw);
            ZrAttendanceSetting startSetting;
            if (list.size() > 0) {//开始日期以前有设置
                startSetting = list.get(0);
            } else {
                String departHead = baseDepartmentUserService.isDepartHead(userId);
                if (!StringUtil.iszNull(departHead)) {//是领导
                    QueryWrapper<ZrAttendanceSetting> qw0 = new QueryWrapper<>();
                    qw0.isNull("target_id");//部门领导这两个为空
                    qw0.isNull("type");
                    qw0.lt("start_date", inputParam.getStartDate());//得到开始日期前的设置
                    List<ZrAttendanceSetting> list0 = zrAttendanceSettingService.list(qw0);
                    if (list0.size() > 0) {//领导的有设置
                        startSetting = list0.get(0);
                    } else {//设置部门和默认
                        startSetting = getZrAttendanceSetting2(inputParam, userId);
                    }
                } else {//设置部门和默认
                    startSetting = getZrAttendanceSetting2(inputParam, userId);
                }
            }
            //查找在之间的设置
            QueryWrapper<ZrAttendanceSetting> qw1 = new QueryWrapper<>();
            qw1.eq("target_id", userId);
            qw1.eq("type", 1);//先找个人设定
            qw1.between("start_date", inputParam.getStartDate(), inputParam.getEndDate());//得到开始日期前的设置
            qw1.orderByAsc("start_date");
            List<ZrAttendanceSetting> avalSettings;
            avalSettings = zrAttendanceSettingService.list(qw1);
            if (avalSettings.size() == 0) {//没有找到，找领导
                String departHead = baseDepartmentUserService.isDepartHead(userId);
                if (!StringUtil.iszNull(departHead)) {//是领导
                    QueryWrapper<ZrAttendanceSetting> qw0 = new QueryWrapper<>();
                    qw0.isNull("target_id");//部门领导这两个为空
                    qw0.isNull("type");
                    qw0.between("start_date", inputParam.getStartDate(), inputParam.getEndDate());//得到开始日期前的设置
                    qw0.orderByAsc("start_date");
                    avalSettings = zrAttendanceSettingService.list(qw0);
                    if (avalSettings.size() == 0) {//领导的没有设置，找部门的
                        avalSettings = getZrAttendanceSettingsBetween(inputParam, userId);
                    }
                } else {//设置部门
                    avalSettings = getZrAttendanceSettingsBetween(inputParam, userId);
                }
            }
            avalSettings.add(startSetting);
            //转化为map方便使用
            Map<LocalDate, ZrAttendanceSetting> avalMap = new LinkedHashMap<>();
            for (ZrAttendanceSetting zr :
                    avalSettings) {
                avalMap.put(zr.getStartDate(), zr);
            }
            //一天一天的算时数
            ZrAttendanceSetting currentSetting = startSetting;
            int count = 0;
            while (!inputParam.getStartDate().equals(inputParam.getEndDate())) {
                //如果统计的当天有设置，当前设置就是统计当天的设置
                if (avalMap.get(inputParam.getStartDate()) != null) {
                    currentSetting = avalMap.get(inputParam.getStartDate());
                }
                if (currentSetting.getWorkType() == 0 || currentSetting.getWorkType() == 2 || currentSetting.getWorkType() == 3) {
                    DateEasy i = new DateEasy(inputParam.getStartDate());
                    int nn = i.getDayOfWeek();
                    count += NumberUtil.toIntCase(BeanUtils.beanToMap(currentSetting).get("att" + nn) + "");
                } else if (currentSetting.getWorkType() == 4) {
                    double step = currentSetting.getTotalHours() / 7.0;//平均分
                    count += step;
                } else if (currentSetting.getWorkType() == 1) {
                    if (isBig(currentSetting, new DateEasy(inputParam.getStartDate()))) {
                        DateEasy i = new DateEasy(inputParam.getStartDate());
                        int nn = i.getDayOfWeek();
                        if (!(nn == 6 || nn == 7)) {
                            count += NumberUtil.toIntCase(BeanUtils.beanToMap(currentSetting).get("att" + nn) + "");
                        }
                    } else {
                        DateEasy i = new DateEasy(inputParam.getStartDate());
                        int nn = i.getDayOfWeek();
                        int x = NumberUtil.toIntCase(BeanUtils.beanToMap(currentSetting).get("att" + nn) + "");
                        if (nn == 6 && x == 0) {//小周但周六没有设置的情况
                            x = ZrAttendanceSetting.WORKTIME;
                        }
                        count += x;
                    }
                }
                LocalDate d = inputParam.getStartDate().plusDays(1);
                inputParam.setStartDate(d);
            }
            return count;
        }
        return 0;
    }

    /**
     * 找到一个月内的设置项目
     *
     * @param inputParam
     * @param userId
     * @return
     */
    private List<ZrAttendanceSetting> getZrAttendanceSettingsBetween(InputParam inputParam, String userId) {
        List<ZrAttendanceSetting> avalSettings;
        QueryWrapper<ZrAttendanceSetting> qw2 = new QueryWrapper<>();
        qw2.eq("target_id", userId);
        qw2.eq("type", 0);
        qw2.between("start_date", inputParam.getStartDate(), inputParam.getEndDate());//得到开始日期前的设置
        qw2.orderByAsc("start_date");
        avalSettings = zrAttendanceSettingService.list(qw2);
        return avalSettings;
    }

    /**
     * type为2月的时候找部门或默认设置
     *
     * @param inputParam
     * @param userId
     * @return
     */
    private ZrAttendanceSetting getZrAttendanceSetting2(InputParam inputParam, String userId) {
        ZrAttendanceSetting startSetting;
        QueryWrapper<ZrAttendanceSetting> qw1 = new QueryWrapper<>();
        qw1.inSql("target_id", "SELECT depart_id FROM base_department_user WHERE user_id='" + userId + "'");
        qw1.eq("type", 0);//再找部门设定
        qw1.lt("start_date", inputParam.getStartDate());//得到开始日期前的设置
        qw1.orderByDesc("target_id","start_date");
        List<ZrAttendanceSetting> list1 = zrAttendanceSettingService.list(qw1);

        if (list1.size() > 0) {
            //有两个以上的部门都设置了就取总数最多的
            doAvalDepartSet(list1);
            startSetting = list1.get(0);
        } else {
            startSetting = ZrAttendanceSetting.getInstanceDefault(inputParam);
            startSetting.setStartDate(inputParam.getStartDate());
        }
        return startSetting;
    }

    /**
     * 找部门与默认
     *
     * @param inputParam
     * @param userId
     * @return
     */
    private int findDepartAndDefault(InputParam inputParam, String userId) {
        QueryWrapper<ZrAttendanceSetting> qw1 = new QueryWrapper<>();
        qw1.inSql("target_id", "SELECT depart_id FROM base_department_user WHERE user_id='" + userId + "'");
        qw1.eq("type", 0);//再找部门的设定
        qw1.lt("start_date", LocalDate.now());//设定时间小于今天
        qw1.orderByDesc("target_id", "start_date");
        List<ZrAttendanceSetting> list1 = zrAttendanceSettingService.list(qw1);
        if (list1.size() > 0) {//部门找到了
            //有两个以上的部门都设置了就取总数最多的
            doAvalDepartSet(list1);
            int total = 0;
            if (inputParam.getType() == 0) {
                total = getDayTotal(list1);
            } else if (inputParam.getType() == 1) {
                total = getWeekTotal(list1, inputParam);
            }
            return total;
        } else {//都没有找到最默认的
            InputParam in = new InputParam();
            List l = new ArrayList();
            ZrAttendanceSetting z = ZrAttendanceSetting.getInstanceDefault(in);//用默认的
            l.add(z);
            int total = 0;
            if (inputParam.getType() == 0) {
                total = getDayTotal(l);
            } else if (inputParam.getType() == 1) {
                total = ZrAttendanceSetting.WORKTIME * 5;
            }
            return total;
        }
    }


    /**
     * 处理两个部门以上都设置了的情况
     *
     * @param list1
     */
    private void doAvalDepartSet(List<ZrAttendanceSetting> list1) {
        if (list1.size() == 1)
            return;
        //每个部门中的第一个
        Map<String, ZrAttendanceSetting> perDepartFirstMap = new LinkedHashMap<>();
        for (ZrAttendanceSetting zr :
                list1) {
            if (!perDepartFirstMap.containsKey(zr.getTargetId())) {
                perDepartFirstMap.put(zr.getTargetId(), zr);
            }
        }
        List<ZrAttendanceSetting> t = new ArrayList();
        t.addAll(perDepartFirstMap.values());
        if (t.size() == 1)
            return;
        //排序
        Collections.sort(t, new Comparator<ZrAttendanceSetting>() {
            @Override
            public int compare(ZrAttendanceSetting o1, ZrAttendanceSetting o2) {
                int totalWeek1 = 0;
                int totalWeek2 = 0;
                if (o1.getWorkType() != 4) {
                    totalWeek1 = o1.getAtt1() + o1.getAtt2() + o1.getAtt3() + o1.getAtt4() + o1.getAtt5() + o1.getAtt6() + o1.getAtt7();
                } else {
                    totalWeek1 = o1.getTotalHours();
                }
                if (o2.getWorkType() != 4) {
                    totalWeek2 = o2.getAtt1() + o2.getAtt2() + o2.getAtt3() + o2.getAtt4() + o2.getAtt5() + o2.getAtt6() + o2.getAtt7();
                } else {
                    totalWeek2 = o2.getTotalHours();
                }
                return totalWeek2 - totalWeek1;
            }
        });
        list1.clear();
        list1.addAll(t);
    }

    /**
     * 日找前一天的内容
     *
     * @param list
     * @return
     */
    private int getDayTotal(List<ZrAttendanceSetting> list) {
        ZrAttendanceSetting zs = list.get(0);
        if (zs.getWorkType() == 4) {//4就不能统计日的，返回-1
            return -1;
        }
        DateEasy da = new DateEasy();
        da.addDate(-1);//前一天
        int nn = da.getDayOfWeek();
        return NumberUtil.toIntCase(BeanUtils.beanToMap(zs).get("att" + nn) + "");
    }

    /**
     * 周找到这一周总时数
     *
     * @param list
     * @return
     */
    @SneakyThrows
    private int getWeekTotal(List<ZrAttendanceSetting> list, InputParam inputParam) {
        ZrAttendanceSetting zs = list.get(0);
        if (zs.getWorkType() == 4) {
            return NumberUtil.toIntCase(zs.getTotalHours() + "");
        } else if (zs.getWorkType() == 1) {
            return dxzTotal(zs, new DateEasy());
        }
        int count = 0;
        for (int i = 1; i <= 7; i++) {
            int nn = NumberUtil.toIntCase(BeanUtils.beanToMap(zs).get("att" + i) + "");
            count += nn;
        }
        return count;
    }

    /**
     * 返回大小周的天数
     * @param zs da
     * @return
     */
    private int dxzTotal(ZrAttendanceSetting zs, DateEasy da) {
        boolean big = isBig(zs, da);
        if (big) {
            return zs.getAtt1() + zs.getAtt2() + zs.getAtt3() + zs.getAtt4() + zs.getAtt5();
        } else {
            return zs.getAtt1() + zs.getAtt2() + zs.getAtt3() + zs.getAtt4() + zs.getAtt5() + zs.getAtt6();
        }
    }

    /**
     * 统计时间所在周是大周还是小周
     *
     * @param zs
     * @param da
     * @return
     */
    private boolean isBig(ZrAttendanceSetting zs, DateEasy da) {
        //设置周是大周还是小周
        boolean big = false;
        int count = 0;
        for (int i = 1; i <= 7; i++) {
            int nn = NumberUtil.toIntCase(BeanUtils.beanToMap(zs).get("att" + i) + "");
            if (nn == 0) {
                count++;
            }
        }
        if (count == 1) {
            big = false;
        } else if (count == 2) {
            big = true;
        }
        //统计周是大周还是小周
        if (da.getDayOfWeek() == 1) {
            da.addDate(-7);
        } else {
            da = DateEasy.getTimesWeekMorning(da);
        }
        //得到设置开始时间
        DateEasy start = new DateEasy(zs.getStartDate());
        DateEasy end = new DateEasy(da);
        long[] dt = DateEasy.getDistanceTimes(start.toYYYYhMMhDDhHHcMMcSS(), end.toYYYYhMMhDDhHHcMMcSS());
        long distance = dt[0];
        distance = distance / 7;
        if (distance % 2 != 0) {
            big = !big;
        }
        return big;
    }

    //判断用户是否是老板或者admin
    private boolean isAdminOrBoss(String userId) {
        boolean isAdmin = baseRoleService.hasRole(SysUtil.ROLE_FLAG_ADMIN, userId);
        boolean isBoss = baseRoleService.hasRole(SysUtil.ROLE_FLAG_BOSS, userId);
        //人事或者admin才可以重置密码
        if (isAdmin || isBoss) {
            return true;
        }
        return false;
    }
}
